home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / gui / prcgntn1.lha / Precognition / source / ListBrowser.c < prev    next >
C/C++ Source or Header  |  1992-12-23  |  12KB  |  480 lines

  1. /* ==========================================================================
  2. **
  3. **                         ListBrowser.c
  4. **
  5. ** ⌐1991 WILLISoft
  6. **
  7. ** ==========================================================================
  8. */
  9.  
  10. #include <string.h>
  11. #include "minmax.h"
  12. #include "ListBrowser.h"
  13. #include "ListBrowserClass.h"
  14. #include "EmbossedGadgetClass.h"
  15. #include "precognition.h"
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include "amigamem.h"
  20.  
  21. #define CHAR_WIDTH  8   /* Width  of Topaz 80 font.*/
  22. #define CHAR_HEIGHT 9   /* Height of Topaz 80 font.*/
  23. #define BROWSER_ENTRY_HEIGHT (CHAR_HEIGHT + 1)
  24. #define BORDER_WIDTH 3
  25. #define BASELINE     8
  26.  
  27. #define isSelected(q) (q & ENTRY_SELECTED)
  28.  
  29. const StringList *ListBrowser_StringList_of( ListBrowser *self )
  30. {
  31.    return &self->List;
  32. }
  33.  
  34. void ListBrowser_Init( ListBrowser   *self,
  35.                        PIXELS         LeftEdge,
  36.                        PIXELS         TopEdge,
  37.                        PIXELS         Width,
  38.                        PIXELS         Height,
  39.                        pcg_3DPens     Pens,
  40.                        BOOL           SelectMany )
  41. {
  42.  
  43.    EmbossedGadget_Init( &self->eg, LeftEdge, TopEdge, 0, 0,
  44.       GADGHNONE, RELVERIFY, BOOLGADGET, Pens, NULL );
  45.  
  46.    self->eg.isa       = ListBrowserClass();
  47.    self->SelectMany   = SelectMany;
  48.    self->YOffset      = 0;
  49.    SetLocation( self, LeftEdge, TopEdge );
  50.    SetSize( self, Width, Height );
  51.  
  52.    /* Initialize List structure... */
  53.    StringList_Init( &self->List, TRUE );
  54.  
  55. }
  56.  
  57. void ListBrowser_CleanUp( ListBrowser *self )
  58. {
  59.    StringList *sl;
  60.  
  61.    StringList_CleanUp( StringList_of(self) );
  62.    EmbossedGadget_CleanUp( self );
  63. }
  64.  
  65. Point ListBrowser_AskSize( ListBrowser *self,
  66.                            PIXELS       Width,
  67.                            PIXELS       Height )
  68. {
  69.    Point size;
  70.    short nCols, nRows;
  71.  
  72.    nCols = ( Width-BORDER_WIDTH*2  ) / CHAR_WIDTH;
  73.    nRows = ( Height-BORDER_WIDTH*2 ) / BROWSER_ENTRY_HEIGHT;
  74.  
  75.    nCols = MAX( nCols, 5 );
  76.    nRows = MAX( nRows, 5 );
  77.  
  78.    size.x = nCols*CHAR_WIDTH           + BORDER_WIDTH*2;
  79.    size.y = nRows*BROWSER_ENTRY_HEIGHT + BORDER_WIDTH*2;
  80.  
  81.    return size;
  82. }
  83.  
  84.  
  85. Point ListBrowser_SetSize( ListBrowser *self,
  86.                             PIXELS       Width,
  87.                             PIXELS       Height )
  88. {
  89.    Point size;
  90.  
  91.    size = AskSize( self, Width, Height );
  92.  
  93.    Forbid(); /* Don't want Intuition looking at these while we modify em. */
  94.    self->eg.Size     = size;
  95.    self->eg.g.Width  = size.x - BORDER_WIDTH*2;
  96.    self->eg.g.Height = size.y - BORDER_WIDTH*2;
  97.  
  98.    pcg_Init3DBox(  self->eg.BoxBorder,
  99.                    -BORDER_WIDTH, -BORDER_WIDTH,
  100.                    size.x, size.y,
  101.                    self->eg.Pens.BrightPen,  self->eg.Pens.DarkPen,
  102.                    self->eg.BoxBorder->BottomRight.NextBorder );
  103.    Permit();
  104.  
  105.  
  106.    self->nColumns = ( size.x-BORDER_WIDTH*2 ) / CHAR_WIDTH;
  107.    self->nRows    = ( size.y-BORDER_WIDTH*2 ) / BROWSER_ENTRY_HEIGHT;
  108.  
  109.    return size;
  110. }
  111.  
  112. Point ListBrowser_SetLocation( ListBrowser *self,
  113.                                PIXELS       LeftEdge,
  114.                                PIXELS       TopEdge )
  115. {
  116.    Point location;
  117.  
  118.    Forbid();
  119.    self->eg.Location.x = LeftEdge;
  120.    self->eg.Location.y = TopEdge;
  121.    self->eg.g.LeftEdge = LeftEdge + BORDER_WIDTH;
  122.    self->eg.g.TopEdge  = TopEdge  + BORDER_WIDTH;
  123.    Permit();
  124.  
  125.  
  126.    return location;
  127. }
  128.  
  129. USHORT ListBrowser_SetYOffset( ListBrowser *self,
  130.                                USHORT       YOffset )
  131. {
  132.    SHORT MaxY;
  133.  
  134.    MaxY          = MAX( self->List.nEntries-self->nRows, 0 );
  135.    self->YOffset = MIN( YOffset, MaxY );
  136.  
  137.    return self->YOffset;
  138. }
  139.  
  140.  
  141.  
  142. #define DESELECT_ALL(b) ListBrowser_SelectAll(b, FALSE)
  143.  
  144. void ListBrowser_SelectAll( ListBrowser *self, BOOL Select )
  145. /* Selects or deselects everything in the list. */
  146. {
  147.    USHORT i;
  148.  
  149.    for (i=0; i<self->List.nEntries; i++)
  150.    {
  151.       if (Select)
  152.          self->List.Qualifiers[i] |= ENTRY_SELECTED;
  153.       else
  154.          self->List.Qualifiers[i] &= (UBYTE) ~ENTRY_SELECTED;
  155.    }
  156.  
  157. }
  158.  
  159. void ListBrowser_SelectString( ListBrowser  *self,
  160.                                USHORT        i,
  161.                                BOOL          Select   )
  162. {
  163.    if ((! self->SelectMany) && (Select))
  164.       DESELECT_ALL( self );
  165.  
  166.    if (Select)
  167.       self->List.Qualifiers[i] |= ENTRY_SELECTED;
  168.    else
  169.       self->List.Qualifiers[i] &= ~ENTRY_SELECTED;
  170. }
  171.  
  172. void ListBrowser_DrawEntry( ListBrowser    *self,
  173.                             RastPort       *RPort,
  174.                             USHORT          index )
  175. {
  176.    USHORT count, X, Y, Xend, Yend;
  177.    UBYTE qual, succ, pred;
  178.    char **Entries;
  179.    UBYTE *Qualifiers;
  180.    pcg_3DPens pens;
  181.  
  182.    Entries    = self->List.Entries;
  183.    Qualifiers = self->List.Qualifiers;
  184.  
  185.    X      = self->eg.Location.x + BORDER_WIDTH;
  186.    Y      = self->eg.Location.y + BORDER_WIDTH
  187.             + (index-self->YOffset)*BROWSER_ENTRY_HEIGHT;
  188.    Xend   = X + self->eg.g.Width-1;
  189.    Yend   = Y + BROWSER_ENTRY_HEIGHT;
  190.    pens   = self->eg.Pens;
  191.  
  192.    SetDrMd( RPort, JAM1 );
  193.    /* Clear the entry. */
  194.    SetAPen( RPort, pens.BackPen );
  195.    RectFill( RPort, X, Y, Xend, Yend );
  196.  
  197.  
  198.    qual = Qualifiers[index];
  199.    if (index)
  200.       pred = Qualifiers[index-1];
  201.    else
  202.       pred = 0;
  203.  
  204.    if (index+1 < self->List.nEntries)
  205.       succ = Qualifiers[index+1];
  206.    else
  207.       succ = 0;
  208.  
  209.  
  210.    if (qual & ENTRY_SPECIAL)
  211.       SetAPen( RPort, pens.FrontPen+1 );
  212.    else
  213.       SetAPen( RPort, pens.FrontPen );
  214.  
  215.    Move( RPort, X+1, Y+BASELINE );
  216.    count = strlen( Entries[index] );
  217.    count = MIN( self->nColumns, count ); 
  218.    Text( RPort, Entries[index], count );
  219.  
  220.  
  221.    if (isSelected(qual))
  222.    {
  223.       SetDrMd( RPort, COMPLEMENT );
  224.  
  225.       /* Draw 3D lines. */
  226.       RectFill( RPort, X, Y, Xend, Yend );
  227.       SetDrMd(  RPort, JAM1 );
  228.       SetAPen( RPort, pens.DarkPen );
  229.       Move( RPort, X, Yend );
  230.       Draw( RPort, X, Y );
  231.  
  232.       SetAPen( RPort, pens.BrightPen ); /* Right side bar. */
  233.       Move( RPort, Xend, Y );
  234.       Draw( RPort, Xend, Yend );
  235.    }
  236.  
  237.    /* Draw top bar. */
  238.    if (( (!isSelected(pred)) && isSelected(qual)))
  239.          /* previous is not selected, entry is  */
  240.    {
  241.       SetAPen( RPort, pens.DarkPen );
  242.       Move( RPort, X,    Y );
  243.       Draw( RPort, Xend, Y );
  244.    }
  245.    else if (isSelected(pred) && (!isSelected(qual)))
  246.       /* previous is selected, entry is not */
  247.    {
  248.       SetAPen( RPort, pens.BrightPen );
  249.       Move( RPort, X,    Y );
  250.       Draw( RPort, Xend, Y );
  251.    }
  252.  
  253.    /* Draw bottom bar */
  254.    if ((!isSelected(succ)) && isSelected(qual))
  255.       /* successor is not selected, entry is  */
  256.    {
  257.       SetAPen( RPort, pens.BrightPen );
  258.       Move( RPort, X,    Yend );
  259.       Draw( RPort, Xend, Yend );
  260.    }
  261.    else if (isSelected(succ) && (!isSelected(qual)))
  262.       /* successor is selected, entry is not */
  263.    {
  264.       SetAPen( RPort, pens.DarkPen );
  265.       Move( RPort, X,    Yend );
  266.       Draw( RPort, Xend, Yend );
  267.    }
  268. }
  269.  
  270.  
  271. void ListBrowser_Render( ListBrowser *self,
  272.                          RastPort    *RPort )
  273. {
  274.    USHORT        X, Y, Xend, Yend;
  275.    USHORT        i, j;
  276.  
  277.    X      = self->eg.g.LeftEdge;/* + BORDER_WIDTH;*/
  278.    Y      = self->eg.g.TopEdge; /*  + BORDER_WIDTH;*/
  279.    Xend   = X + self->eg.g.Width-1;
  280.    Yend   = Y + self->eg.g.Height-1;
  281.  
  282.  
  283.    DrawBorder( RPort, self->eg.BoxBorder, self->eg.g.LeftEdge, self->eg.g.TopEdge );
  284.  
  285.    /* Clear the display area. */
  286.    SetDrMd( RPort, JAM1 );
  287.    SetAPen( RPort, self->eg.Pens.BackPen );
  288.    RectFill( RPort, X, Y, Xend, Yend );
  289.  
  290.  
  291.    /* Display the list */
  292.    for( j=0, i=self->YOffset; j<self->nRows; j++, i++)
  293.    {
  294.       if (i>=self->List.nEntries) break;
  295.       ListBrowser_DrawEntry( self, RPort, i );
  296.    }
  297. }
  298.  
  299.  
  300. void ListBrowser_ChangeHighlight( ListBrowser *self,
  301.                                   USHORT       new_highlighted_entry, /* index */
  302.                                   RastPort    *RPort )
  303. {
  304.    USHORT        i, j;
  305.    UBYTE  *Qualifiers;
  306.  
  307.  
  308.    /* Display the list */
  309.    Qualifiers = self->List.Qualifiers;
  310.  
  311.    /* Deselect the old one. */
  312.    i = self->YOffset;
  313.    for (j=0; j<self->nRows; j++, i++)
  314.    {
  315.       if (i >= self->List.nEntries) break;
  316.  
  317.       if (isSelected(Qualifiers[i]) )
  318.       {
  319.          /* If this is the old highlight */
  320.          Qualifiers[i] &= ~ENTRY_SELECTED;
  321.          ListBrowser_DrawEntry( self, RPort, i );
  322.       }
  323.    }
  324.  
  325.    Qualifiers[new_highlighted_entry] |= ENTRY_SELECTED;
  326.  
  327.    if ((new_highlighted_entry - self->YOffset >= 0) &&
  328.        (new_highlighted_entry - self->YOffset < self->nRows))
  329.       ListBrowser_DrawEntry( self, RPort, new_highlighted_entry );
  330.  
  331. }
  332.  
  333.  
  334. void ListBrowser_Refresh( ListBrowser *self )
  335. {
  336.    struct pcgWindow *window;
  337.  
  338.    window = InteractorWindow( self );
  339.    Render( self, window->Window->RPort );
  340. }
  341.  
  342.  
  343.  
  344. void ListBrowser_AddString( ListBrowser    *self,
  345.                             char           *entry,
  346.                             UBYTE           qualifier )
  347. {
  348.    if ((! self->SelectMany) && isSelected(qualifier))
  349.       DESELECT_ALL( self );
  350.       /* This new entry is selected, so all others must be deselected. */
  351.  
  352.    StringList_AddString( &self->List, entry, qualifier );
  353. }
  354.  
  355.  
  356. BOOL ListBrowser_DeleteString( ListBrowser *self, USHORT i )
  357. {
  358.    BOOL result;
  359.    StringList *sl;
  360.    
  361. /*DUMPWAIT("ListBrowser_DeleteString\n");*/
  362.  
  363.    sl = StringList_of(self);
  364.    
  365.    result = StringList_DeleteString( sl, i );
  366.  
  367.    ListBrowser_SetYOffset( self, self->YOffset );
  368.  
  369. /*DUMPWAIT("end ListBrowser_DeleteString\n");*/
  370.  
  371.    return result;
  372.  
  373. }
  374.  
  375. BOOL ListBrowser_DeleteAllStrings( ListBrowser *self )
  376. {
  377.    BOOL result;
  378.  
  379.    result = StringList_DeleteAllStrings( &self->List );
  380.    ListBrowser_SetYOffset( self, self->YOffset );
  381.  
  382.    return result;
  383. }
  384.  
  385.  
  386.  
  387. #define CLAIM_EVENT(b,e) (&b->eg.g == (Gadget *) e->IAddress)
  388.  
  389. USHORT ListBrowser_Respond( ListBrowser  *self,
  390.                             IntuiMessage *Event )
  391. {
  392.    Point        Mouse;
  393.    USHORT       entry_no;
  394.    USHORT       response = 0;
  395.    UBYTE        qual;
  396.  
  397.    switch (Event->Class)
  398.    {
  399.       case REFRESHWINDOW:
  400.          ListBrowser_Render( self, Event->IDCMPWindow->RPort );
  401.          response = RESPONDED;
  402.          break;
  403.  
  404.       case GADGETUP:
  405.          if (CLAIM_EVENT(self, Event))
  406.          {
  407.             /* Translate into Gadget-Relative Coordinates. */
  408.             GadgetRelativeCoords( &self->eg.g, Event, &Mouse );
  409.             entry_no = (Mouse.y - BORDER_WIDTH) / BROWSER_ENTRY_HEIGHT
  410.                         + self->YOffset;
  411.             entry_no = MAX( entry_no, 0 );
  412.  
  413.             qual = self->List.Qualifiers[entry_no];
  414.  
  415.             if ( entry_no < self->List.nEntries )
  416.             {
  417.                if (self->SelectMany)
  418.                {
  419.                   SelectString( self, entry_no, !isSelected(qual) );
  420.                   ListBrowser_DrawEntry( self,
  421.                      Event->IDCMPWindow->RPort, entry_no );
  422.                }
  423.                else
  424.                {
  425.                   if (!isSelected(qual)) /* Only select if not already.  */
  426.                   {                      /* (Avoids ugly screen update.) */
  427.                      ListBrowser_ChangeHighlight( self, entry_no,
  428.                            Event->IDCMPWindow->RPort );
  429.                   }
  430.                }
  431.             }
  432.             response = RESPONDED | CHANGED_STATE | CONSUMED_EVENT;
  433.          }
  434.          break;
  435.  
  436.    }
  437.    return response;
  438. }
  439.  
  440.  
  441.  
  442. BOOL ListBrowser_elaborated = FALSE;
  443.  
  444. struct StringListerClass ListBrowser_Class;
  445.  
  446. void ListBrowserClass_Init( struct StringListerClass *class )
  447. {
  448.  
  449.    StringListerClass_Init( class );
  450.    EmbossedGadgetClass_Init( class );
  451.    class->isa         = StringListerClass();
  452.    class->ClassName   = "ListBrowser";
  453.    class->CleanUp     = ListBrowser_CleanUp;
  454.    class->AskSize     = ListBrowser_AskSize;
  455.    class->SetSize     = ListBrowser_SetSize;
  456.    class->SizeFlags   = GraphicObject_SizeFlagsAll;
  457.    class->SetLocation = ListBrowser_SetLocation;
  458.    class->Respond     = ListBrowser_Respond;
  459.    class->Render      = ListBrowser_Render;
  460.    class->Refresh     = ListBrowser_Refresh;
  461.  
  462.    class->AddString     = ListBrowser_AddString;
  463.    class->DeleteString  = ListBrowser_DeleteString;
  464.    class->DeleteAllStrings  = ListBrowser_DeleteAllStrings;
  465.    class->StringList_of = ListBrowser_StringList_of;
  466.    class->SelectString  = ListBrowser_SelectString;
  467. }
  468.  
  469.  
  470. struct StringListerClass *ListBrowserClass( void )
  471. {
  472.    if (! ListBrowser_elaborated)
  473.    {
  474.       ListBrowserClass_Init( &ListBrowser_Class );
  475.       ListBrowser_elaborated = TRUE;
  476.    }
  477.  
  478.    return &ListBrowser_Class;
  479. }
  480.